const KEY_STORAGE_CACHE_DATA = "CACHE_DATA";
import {
	readStorage,
	saveStorage
} from "./storageUtil";
import {
	isEmpty
} from "./util";

const Max_Cache_Data_Size = 1024 * 1024 * 30; // 以字节为单位 30M
let Cache_Data = null; // {size, data: {key: {size, filePath, createTime}}}
// 获取缓存数据
function getCacheDataMap() {
	if (!Cache_Data) {
		let storageData = readStorage(KEY_STORAGE_CACHE_DATA);
		if (isEmpty(storageData)) {
			updateStorageCacheData({
				size: 0,
				data: {}
			})
		} else {
			Cache_Data = storageData;
		}
	}
	return Cache_Data;
}
// 移除缓存数据
function removeStorageCacheData(key, callback) {
	let cacheData = getCacheDataMap();
	const keyData = cacheData.data[key]; // 对应key 是否有数据
	if (keyData) {
		// 删除文件
		uni.removeSavedFile({
			filePath: keyData.filePath,
			success: (res) => {
				cacheData.size -= keyData.size; // 总尺寸缩减
				delete cacheData.data[key]; // 移除数据记录
				updateStorageCacheData(cacheData); // 更新缓存数据表
				if (typeof callback == 'function') callback();
			},
			fail: (error) => {
				throw new Error(`文件删除失败${error.errMsg}=>${keyData.filePath}`)
			}
		})
	} else {
		if (typeof callback == 'function') callback();
	}
}
/**
 * 新增缓存数据
 * @param {Object} key key
 * @param {Object} data 数据
 */
function appendStorageCacheData(key, data) {
	// 先删除原有重叠缓存数据
	removeStorageCacheData(key, () => {
		let cacheData = getCacheDataMap();
		cacheData.data[key] = data;
		cacheData.size += data.size;
		updateStorageCacheData(cacheData);
		reduceCacheData();
	});
}

/**
 * 缓存数据超出缓存数据大小限制后，需要缩减缓存数据表，按照存储时间先进先出
 */
function reduceCacheData() {
	let cacheData = getCacheDataMap();
	let dataList = [];
	Object.keys(cacheData.data).forEach(key => {
		dataList.push({
			...cacheData.data[key],
			key
		})
	})
	dataList.sort((a, b) => {
		return a.createTime - b.createTime
	})
	if (cacheData.size > Max_Cache_Data_Size && cacheData.data.length > 1) {
		removeStorageCacheData(dataList[0].key, () => {
			reduceCacheData()
		})
	}
}
/**
 * 更新缓存
 * @param {Object} cacheData
 */
function updateStorageCacheData(cacheData) {
	Cache_Data = cacheData;
	saveStorage(KEY_STORAGE_CACHE_DATA, cacheData);
}

function cacheData(param = {
	key,
	url,
	suffix,
	callback
}) {
	const {
		key,
		url,
		suffix = "",
		callback
	} = param
	if (!key || !url) throw new Error("cacheData key|url 不能为空");
	let currentCache = getCacheDataMap();
	let cacheDataFilePath = currentCache.data[key] ? currentCache.data[key].filePath : null;
	if (cacheDataFilePath) { // 有记录
		// 重新缓存，针对有记录，但是没有查找到文件的情况，为保证安全，先删除，再存储
		let reCache = () => {
			removeStorageCacheData(key, () => {
				cacheData({
					key,
					url,
					suffix,
					callback
				});
			});
		}
		// 查文件，因为可能被清除了。
		uni.getFileInfo({
			filePath: cacheDataFilePath,
			success: (res) => {
				// 文件有
				if (res.size > 0) { // 尺寸是否大于0 大于说明真实存在，返回缓存的地址
					if (typeof callback == "function") callback(cacheDataFilePath);
				} else { // 否则移除记录，重新存储
					reCache();
				}
			},
			fail: (error) => {
				reCache();
			}
		})
		return;
	}

	let filePath;
	// #ifdef MP
	filePath = `${wx.env.USER_DATA_PATH}/${key}${suffix?"."+suffix:suffix}`;
	// #endif
	// #ifndef MP
	filePath = `${key}${suffix?"."+suffix:suffix}`;
	// #endif

	// 下载并保存文件，成功后记录
	// 下载失败， 返回元数据
	let downloadFailFn = (filePath) => {
		if (typeof callback == "function") callback(filePath);
	}
	// 下载成功， 保存文件
	let downloadSuccessFn = (tempFilePath) => {
		uni.saveFile({
			tempFilePath,
			success: (res) => {
				saveFileSuccessFn(res.savedFilePath);
			},
			fail: (error) => {
				saveFileFail(tempFilePath)
			}
		})
	}
	// 保存失败 返回元数据
	let saveFileFail = (filePath) => {
		if (typeof callback == 'function') callback(filePath);
	}
	// 保存成功，计入表格
	let saveFileSuccessFn = (filePath) => {
		uni.getSavedFileInfo({
			filePath,
			success: (res) => {
				appendStorageCacheData(key, {
					filePath,
					size: res.size,
					createTime: res.createTime
				})
				if (typeof callback == 'function') callback(filePath)
			}
		})
	}

	// 下载文件
	uni.downloadFile({
		url,
		filePath,
		success: (res) => {
			if (res.statusCode == 200) {
				downloadSuccessFn(res.tempFilePath ? res.tempFilePath : res.filePath);
			} else {
				downloadFailFn(url)
			}
		},
		fail: (error) => {
			downloadFailFn(url)
		}
	})
}


module.exports = {
	cacheData, // 缓存数据
	getCacheDataMap, // 获取缓存数据查询表
}